﻿using DEL;
using IBLL;
using Microsoft.AspNetCore.Mvc;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using Web.Models;

// 引用业务层，复杂的逻辑由业务逻辑层实现后直接引用 

namespace Web
{
    public abstract class BaseController<TEntity> : Controller where TEntity : BaseT, new()
    {
        //定义一记录日志的容器
        protected static Logger Logger = LogManager.GetCurrentClassLogger();

        //基类的构造函数
        public BaseController()
        {
            SetCurrentEntityService();  //构造函数里面去调用了，此设置当前仓储的抽象方法
            SetEntitysWhereLambda();
            SetPageSize();
            SetOrderLambda();
            SetIsASC();
        }

        #region option
        //定义具体绑定实体T
        protected IBaseService<TEntity> CurrentEntityService { get; set; }
        protected abstract void SetCurrentEntityService();  //子类必须实现，得到具体的实体
                
        

        /// <summary>
        /// 定义用于查询多个结果的lambda表达式:o => o.Id>30
        /// </summary>
        protected Expression<Func<TEntity, bool>> EntitysWhereLambda { get; set; }        
        public virtual void SetEntitysWhereLambda()  //子类可以实现，默认查出所有数据，特别对于大数据更应该进行过滤
        {
            EntitysWhereLambda = o => o.Id > 0;
        }

        //定义用于排序的字段
        protected Expression<Func<TEntity, object>> OrderLambda { get; set; }
        public virtual void SetOrderLambda()    //可以在子类中覆盖此方法，必须是实体中存在的(参考实体定义)，否则出错,例如Id，区分大小写
        {
            OrderLambda = o =>o.SortIndex;
        }

        //定义是否按升序排列
        protected bool IsASC;
        public virtual void SetIsASC()  //可以在子类中覆盖此方法，设置isASC为false则按降序排
        {
            IsASC = true;
        }

        //定义每页显示条数
        protected int PageSize { get; set; }
        public virtual void SetPageSize()   //可以在子类中覆盖此方法，设置每页显示的条数
        {
            PageSize = 10;
        }
        #endregion

        #region Page
        /// <summary>
        /// 列表视图
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual IActionResult Index()
        {
            return View();
        }
        //public virtual IActionResult Index(int id = 1)
        //{
        //    var pageIndex = id;
        //    var routeUrl = HttpContext.Request.Path.ToString();  //例如：/Sys/user/index/ 或者/sys/user/index/1          
        //    routeUrl = routeUrl.Substring(0, routeUrl.LastIndexOf("/"));
        //    routeUrl = routeUrl.TrimEnd('/');
        //    int rowCount, pageCount;
        //    var t = CurrentEntityService.GetPagedEntitysByLambdaAndSort(pageIndex,PageSize,out rowCount, out pageCount,EntitysWhereLambda,OrderByProperty,IsASC);
        //    var pageOption = new MoPagerOption
        //    {
        //        PageIndex = pageIndex,
        //        PageSize = PageSize,
        //        RowCount = rowCount,
        //        PageCount = pageCount,
        //        RouteUrl = routeUrl
        //    };

        //    //分页参数
        //    ViewBag.PagerOption = pageOption;

        //    //数据
        //    return View(t);
        //}

        public virtual IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public virtual IActionResult Create(TEntity item)
        {
            var t = item.GetType();  //获取实例化的子类的类型
            var userId = User.Identity.Name;  //获取登录时存储的用户名称(此处是user.id）      
            item.CreatedBy = int.Parse(userId);            
            CurrentEntityService.AddEntity(item);            
            Logger.Info("-------------------------------增加----------------------------------");
            Logger.Info("用户：" + userId + "，增加一条数据:" + t.Name + "-" + item.Id + "。具体数据：");
            //反射，属性名必须有get,set方法
            //用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了
            foreach (PropertyInfo pi in t.GetProperties())
            {
                var val = pi.GetValue(item, null).ToString();//用pi.GetValue获得值
                string name = pi.Name;//获得属性的名字                        
                Logger.Info(name + ":" + (val == null ? "" : val));
            }
            return View("Index");
        }

        public ActionResult Details(int id)
        {
            TEntity t = CurrentEntityService.GetEntityById(id);
            return View(t);
        }

        public ActionResult Edit(int id)
        {
            TEntity t = CurrentEntityService.GetEntityById(id);
            return View(t);
        }

        [HttpPost]
        public ActionResult Edit(TEntity item)
        {
            try
            {
                var t = item.GetType();  //获取实例化的子类的类型
                var userId = User.Identity.Name;  //获取登录时存储的用户名称(此处是user.id）      
                item.CreatedBy = int.Parse(userId);
                item.UpdatedBy = int.Parse(userId);
                CurrentEntityService.ModifyEntity(item);
                Logger.Info("-------------------------------修改-------------------------------------");
                Logger.Info("用户：" + userId + "，修改一条数据:" + t.Name + "-" + item.Id + "。具体数据：");
                //用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了
                foreach (PropertyInfo pi in t.GetProperties())
                {
                    var val = pi.GetValue(item, null);//用pi.GetValue获得值
                    string name = pi.Name;//获得属性的名字                        
                    Logger.Info(name + ":" + (val == null ? "" : val));
                }

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        public ActionResult Delete(int id)
        {
            TEntity t = CurrentEntityService.GetEntityById(id);
            return View(t);
        }
       
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            try
            {
                CurrentEntityService.DeleteEntityById(id);

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
        #endregion

        #region Ajax
        //获取所有数据，对于大数据表，慎用
        public JsonResult GetAllListToJson()
        {
            return Json(CurrentEntityService.GetAllEntitysList());
        }

        public virtual JsonResult GetPagedListToJson(int? pageindex = 1)
        {
            int pageIndex = pageindex.Value;
            int rowCount = 0, pageCount = 0;
            var data = CurrentEntityService.GetPagedEntitysByLambdaAndSort(pageIndex, PageSize, out rowCount, out pageCount, EntitysWhereLambda, OrderLambda, IsASC);

            //Json格式的要求{rowCount:22,pageCount:2,rows:{}},构造成Json的格式传递
            return Json(new
            {
                rowCount = rowCount,
                pageCount = pageCount,
                rows = data
            });
        }
        
        public JsonResult GetByIdToJson(int id)
        {
            if (id == null)
            {
                return Json(new { Result = "Fail" });
            }
            var data = CurrentEntityService.GetEntityById(id);
            if (data == null)
            {
                return Json(new { Result = "Fail" });
            }
            return Json(data);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids">包括id的字符串，结构为id,id,id,id</param>
        /// <returns></returns>
        public JsonResult DeleteMutiByIds(string ids)
        {
            try
            {
                string[] idArray = ids.Split(',');
                List<int> delIds = new List<int>();
                foreach (string id in idArray)
                {
                    CurrentEntityService.DeleteEntityById(int.Parse(id));
                }
                return Json(new { Result = "Success" });
            }
            catch (Exception ex)
            {
                return Json(new
                {
                    Result = "Faild",
                    Message = ex.Message
                });
            }
        }

        //对于有关联的信息，子类中注意要用override重写
        public virtual JsonResult DeleteById(int id)
        {
            var userId = User.Identity.Name;  //获取登录时存储的用户名称(此处是user.id）
            var t = this.GetType();  //获取实例化的子类的类型
            try
            {
                CurrentEntityService.DeleteEntityById(id);
                Logger.Info("-------------------------------删除-------------------------------------");
                Logger.Info("用户：" + userId + "，删除一条数据：" + t.Name + "-" + id);
                return Json(new { Result = "Success" });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "Faild", Message = ex.Message });
            }
        }

        public JsonResult AddOrModify(TEntity item)
        {
            var userId = User.Identity.Name;  //获取登录时存储的用户名称(此处是user.id）            
            var t = item.GetType();  //获取实例化的子类的类型
            //if (!ModelState.IsValid)
            //{
            //    return Json(new
            //    {
            //        Result = "Faild",
            //        Message = GetModelStateError()
            //    });
            //}
            try
            {
                if (item.Id == 0)
                {
                    item.CreatedBy = int.Parse(userId);
                    item.CreatedOn = DateTime.Now;
                    item.UpdatedBy = int.Parse(userId);
                    item.UpdatedOn = DateTime.Now;
                    CurrentEntityService.AddEntity(item);
                    //CurrentEntityService.AddEntity(item);
                    Logger.Info("-------------------------------增加----------------------------------");
                    Logger.Info("用户：" + userId + "，增加一条数据:" + t.Name + "-" + item.Id + "。具体数据：");
                    //反射，属性名必须有get,set方法
                    //用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了
                    foreach (PropertyInfo pi in t.GetProperties())
                    {
                        string tempName = pi.Name;  //获得属性的名字   
                        var tempVal="";
                        try
                        {
                            tempVal = pi.GetValue(item).ToString();//用pi.GetValue获得值，若值不存在，则要引发异常 
                        }
                        catch
                        {
                            tempVal = "未赋值";
                        }                                               
                        Logger.Info(tempName + ":" + tempVal);
                    }

                }
                else
                {
                    item.UpdatedBy = int.Parse(userId);
                    item.UpdatedOn = DateTime.Now;
                    CurrentEntityService.ModifyEntity(item);
                    Logger.Info("-------------------------------修改-------------------------------------");
                    Logger.Info("用户：" + userId + "，修改一条数据:" + t.Name + "-" + item.Id + "。具体数据：");
                    //用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了
                    foreach (PropertyInfo pi in t.GetProperties())
                    {
                        string tempName = pi.Name;//获得属性的名字
                        var tempVal = "";
                        try
                        {
                            tempVal = pi.GetValue(item).ToString();//用pi.GetValue获得值，若值不存在，则要引发异常 
                        }
                        catch
                        {
                            tempVal = "未赋值";
                        }
                        Logger.Info(tempName + ":" + tempVal);
                    }
                }
                return Json(new { Result = "Success" });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "Faild", Message = ex.Message });
            }
        }
        #endregion

        /// <summary>
        /// 获取服务端验证的第一条错误信息
        /// </summary>
        /// <returns></returns>
        public string GetModelStateError()
        {
            foreach (var item in ModelState.Values)
            {
                if (item.Errors.Count > 0)
                {
                    return item.Errors[0].ErrorMessage;
                }
            }
            return "";
        }
                
    }
}
